package com.seeyon.ctp.rest.resources;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.brwh.entity.TicketGeneralFieldEntity;
import com.seeyon.apps.brwh.kit.DBKit;
import com.seeyon.apps.brwh.kit.StrKit;
import com.seeyon.apps.brwh.service.OCRRecognizeService;
import com.seeyon.cap4.form.api.FormApi4Cap4;
import com.seeyon.cap4.form.bean.FormBean;
import com.seeyon.cap4.form.bean.FormDataMasterBean;
import com.seeyon.cap4.form.bean.FormDataSubBean;
import com.seeyon.cap4.form.bean.FormTableBean;
import com.seeyon.cap4.form.service.CAP4FormCacheManager;
import com.seeyon.cap4.form.service.CAP4FormManager;
import com.seeyon.cap4.form.util.Enums;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.filemanager.dao.AttachmentDAO;
import com.seeyon.ctp.common.filemanager.manager.AttachmentManager;
import com.seeyon.ctp.common.po.filemanager.Attachment;
import com.seeyon.ctp.common.log.CtpLogFactory;
import org.apache.commons.logging.Log;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import www.seeyon.com.utils.UUIDUtil;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 导入发票进行OCR识别
 */
@Path("jssdk")
public class ImportInvoiceBaiDuOrcResources extends BaseResource {
    private static final Log LOG = CtpLogFactory.getLog(ImportInvoiceBaiDuOrcResources.class);
    private final AttachmentManager attachmentManager = (AttachmentManager) AppContext.getBean("attachmentManager");
    private static final AttachmentDAO attachmentDAO = (AttachmentDAO) AppContext.getBean("attachmentDAO");
    private static final OCRRecognizeService oCRRecognizeService = (OCRRecognizeService) AppContext.getBean("oCRRecognizeService");

    @Path("importInvoiceBaiDuData")
    @POST
    @Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response importInvoiceZhuanData(){
        Map<String, Object> resultMap = new HashMap<>();

        try {
            req.setCharacterEncoding("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        MultipartResolver resolver = new CommonsMultipartResolver(req.getSession().getServletContext());
        MultipartHttpServletRequest multipartRequest = resolver.resolveMultipart(req);


        MultiValueMap<String, MultipartFile> multiFileMap = multipartRequest.getMultiFileMap();
        if(multiFileMap.size()<1){
            resultMap.put("code", 500);
            resultMap.put("message", "请上传文件！！！");
            return this.ok(JSONObject.toJSONString(resultMap));
        }
        List<MultipartFile> fileText = multiFileMap.get("files");
        List<MultipartFile> filedList = multiFileMap.get("files");
//        if(fileText.size() != 1){
//            resultMap.put("code", 500);
//            resultMap.put("message", "只能上传单个文件");
//            return this.ok(resultMap);
//        }
        List<Map<String,Object>> resultMapData = new ArrayList<>();
        try {
            resultMapData = oCRRecognizeService.recognize(fileText);
        } catch (Exception e) {
            LOG.info("识别OCR异常：",e);
            resultMap.put("code", 500);
            resultMap.put("message", "识别OCR异常："+e.getMessage());
            return this.ok(JSONObject.toJSONString(resultMap));
        }

        try {
            //获取字段配置信息
            String fieldsMap = multipartRequest.getParameter("fieldsMap");
            Map<String, Object> mappingMap = JSONObject.parseObject(fieldsMap, Map.class);

            //回写附件字段配置
            String hxFjFieldValue = StrKit.str(mappingMap.get("hxFjFieldValue"));

            //多明细表关联字段配置
            String glFieldValue = StrKit.str(mappingMap.get("glFieldValue"));

            //明细表字段映射配置
            List<Map<String, Object>> fieldsMapList = (List<Map<String, Object>>)mappingMap.get("fieldsMap");
            //开始组装回写前端数据格式
            Map<String, Object> dataMap = new HashMap<String, Object>();

            //过滤掉没有配置的字段
            fieldsMapList = fieldsMapList.stream().filter(f -> !StrKit.str(f.get("formField")).equals("")).collect(Collectors.toList());
            //获取主表字段
            List<Map<String, Object>> masterField = fieldsMapList.stream().filter(f -> f.get("formField").toString().split("-")[2].equals("0")).collect(Collectors.toList());
            if (!masterField.isEmpty()) {
                if (resultMapData.size() > 1) {
                    resultMap.put("code", 500);
                    resultMap.put("message", "存在主表字段映射，只支持单张发票识别！！！");
                    return this.ok(JSONObject.toJSONString(resultMap));
                }
            }

            //获取支持多行的字段
            List<Map<String, Object>> dhFieldMapList = fieldsMapList.stream().filter(f -> f.get("isDh").toString().equals("1") && f.get("formField").toString().split("-")[2].equals("1")).collect(Collectors.toList());
            //获取不支持多行的字段
            List<Map<String, Object>> noDhFieldMapList = fieldsMapList.stream().filter(f -> !f.get("isDh").toString().equals("1") && f.get("formField").toString().split("-")[2].equals("1")).collect(Collectors.toList());


            //主表数据
            List<Map<String, Object>> masterDataList = new ArrayList<>();
            //获取主表字段
            for (Map<String, Object> map : masterField) {
                //获取ocr字段
                String ocrFiled = StrKit.str(map.get("ocrFiled")).split("-")[0].toLowerCase();
                String formField = StrKit.str(map.get("formField")).split("-")[0];
                Map<String, Object> stringObjectMap = resultMapData.get(0);
                for (String s : stringObjectMap.keySet()) {
                    if (s.toLowerCase().equals(ocrFiled)) {
                        List<TicketGeneralFieldEntity> valueMapList = (List<TicketGeneralFieldEntity>) stringObjectMap.get(s);
                        TicketGeneralFieldEntity ticketGeneralFieldEntity = valueMapList.get(0);
                        HashMap<String, Object> mapData = new HashMap<>();
                        mapData.put("value", ticketGeneralFieldEntity.getWord());
                        mapData.put("display", ticketGeneralFieldEntity.getWord());
                        mapData.put("auth", "browse");
                        //主表字段
                        HashMap<String, Object> masterMap = new HashMap<>();
                        masterMap.put("fieldId", formField);
                        masterMap.put("fieldData", mapData);
                        masterDataList.add(masterMap);
                    }
                }
            }

            //回写主表附件字段
            if(!hxFjFieldValue.equals("")){
                List<Attachment> attachments = oCRRecognizeService.upField(filedList);
                if(!attachments.isEmpty()){
                    HashMap<String, Object> mapData = new HashMap<>();
                    mapData.put("value", "");
                    mapData.put("display", "");
                    mapData.put("auth", "browse");
                    mapData.put("atts", attachments);
                    //主表字段
                    HashMap<String, Object> masterMap = new HashMap<>();
                    masterMap.put("fieldId", hxFjFieldValue.split("-")[0]);
                    masterMap.put("fieldData", mapData);
                    masterMap.put("formTableName", hxFjFieldValue.split("-")[1]);
                    masterDataList.add(masterMap);
                }
            }


            //总行Map
            ArrayList<Map<String, Object>> zhDataMaps = new ArrayList<>();
            //获取关联字段
            List<Map<String,Object>> glDataList = new ArrayList<>();
            String[] glSplitList = glFieldValue.split(",");
            //获取明细信息
            for (Map<String, Object> resultMapDatum : resultMapData) {
                //随机获取行id
                Long uuid = UUIDUtil.getUUIDLong();
                String tableName = "";
                //明细行Map
                Map<String, Object> subDataListMap = new HashMap<>();
                //明细字段数据集合
                List<Map<String, Object>> subDataFieldList = new ArrayList<>();
                //获取明细表数据
                for (Map<String, Object> subMap : noDhFieldMapList) {
                    //获取ocr字段
                    String ocrFiled = StrKit.str(subMap.get("ocrFiled")).split("-")[0].toLowerCase();
                    //获取字段名称
                    String formFieName = StrKit.str(subMap.get("formField")).split("-")[0];
                    //获取表名
                    tableName = StrKit.str(subMap.get("formField")).split("-")[1];

                    //获取关联字段
                    String glField = "";
                    if(glSplitList.length>0){
                        for (String glSplit : glSplitList) {
                            String[] split = glSplit.split("-");
                            if(split[1].equals(tableName)){
                                glField = split[0];
                            }
                        }
                    }


                    for (String s : resultMapDatum.keySet()) {
                        if (s.toLowerCase().equals(ocrFiled)) {
                            List<TicketGeneralFieldEntity> valueMapList = (List<TicketGeneralFieldEntity>) resultMapDatum.get(s);
                            HashMap<String, Object> mapData = new HashMap<>();
                            if(valueMapList.size()<1){
                                mapData.put("value", "");
                                mapData.put("display", "");
                                mapData.put("auth", "browse");
                            }else{
                                TicketGeneralFieldEntity ticketGeneralFieldEntity = valueMapList.get(0);
                                mapData.put("value", ticketGeneralFieldEntity.getWord());
                                mapData.put("display", ticketGeneralFieldEntity.getWord());
                                mapData.put("auth", "browse");

                                if(glField.equals(formFieName)){
                                    //添加关联字段的值
                                    Map<String, Object> map = new HashMap<>();
                                    map.put("ocrField", ocrFiled);
                                    map.put("ocrFieldVield", ticketGeneralFieldEntity.getWord());
                                    glDataList.add(map);
                                }
                            }
                            //主表字段
                            HashMap<String, Object> subMapData = new HashMap<>();
                            subMapData.put("fieldId", formFieName);
                            subMapData.put("tableName", tableName);
                            subMapData.put("recordId", uuid);
                            subMapData.put("fieldData", mapData);
                            subDataFieldList.add(subMapData);
                        }
                    }
                }
                subDataListMap.put("uuid", uuid);
                subDataListMap.put("hData", subDataFieldList);
                subDataListMap.put("tableName", tableName);
                zhDataMaps.add(subDataListMap);
            }


            //获取多行明细数据
            //判断每行字段最大的行数
            for (Map<String, Object> resultMapDatum : resultMapData) {
                int maxRow = 0;
                for (Map<String, Object> subMap : dhFieldMapList) {
                    //获取ocr字段
                    String ocrFiled = StrKit.str(subMap.get("ocrFiled")).split("-")[0].toLowerCase();
                    for (String s : resultMapDatum.keySet()) {
                        if (s.toLowerCase().equals(ocrFiled)) {
                            List<TicketGeneralFieldEntity> valueMapList = (List<TicketGeneralFieldEntity>) resultMapDatum.get(s);
                            if (valueMapList.size() > maxRow) {
                                maxRow = valueMapList.size();
                            }
                        }
                    }
                }
                //创建多行数据
                for (int i = 0; i < maxRow; i++) {
                    //随机获取行id
                    Long uuid1 = UUIDUtil.getUUIDLong();
                    String tableName1 = "";
                    //明细行Map
                    Map<String, Object> subDataListMap1 = new HashMap<>();
                    //明细字段数据集合
                    List<Map<String, Object>> subDataFieldList1 = new ArrayList<>();
                    //获取明细表数据
                    for (Map<String, Object> subMap : dhFieldMapList) {
                        //获取ocr字段
                        String ocrFiled = StrKit.str(subMap.get("ocrFiled")).split("-")[0].toLowerCase();
                        //获取字段名称
                        String formFieName = StrKit.str(subMap.get("formField")).split("-")[0];
                        //获取表名
                        tableName1 = StrKit.str(subMap.get("formField")).split("-")[1];

                        for (String s : resultMapDatum.keySet()) {
                            if (s.toLowerCase().equals(ocrFiled)) {
                                List<TicketGeneralFieldEntity> valueMapList = (List<TicketGeneralFieldEntity>) resultMapDatum.get(s);
                                HashMap<String, Object> mapData = new HashMap<>();
                                if ((i + 1) > valueMapList.size()) {
                                    mapData.put("value", "");
                                    mapData.put("display", "");
                                    mapData.put("auth", "browse");
                                } else {
                                    TicketGeneralFieldEntity ticketGeneralFieldEntity = valueMapList.get(i);
                                    mapData.put("value", ticketGeneralFieldEntity.getWord());
                                    mapData.put("display", ticketGeneralFieldEntity.getWord());
                                    mapData.put("auth", "browse");
                                }
                                HashMap<String, Object> subMapData = new HashMap<>();
                                subMapData.put("fieldId", formFieName);
                                subMapData.put("tableName", tableName1);
                                subMapData.put("recordId", uuid1);
                                subMapData.put("fieldData", mapData);
                                subDataFieldList1.add(subMapData);
                            }
                        }
                    }

                    if(!glDataList.isEmpty()){
                        for (String s1 : glSplitList) {
                            String[] split = s1.split("-");
                            if(split[1].equals(tableName1)){
                                //设置关联字段值
                                for (Map<String, Object> glData : glDataList) {
                                    String glOcrFiled = StrKit.str(glData.get("ocrField")).toLowerCase();
                                    String ocrFieldVield = StrKit.str(glData.get("ocrFieldVield"));
                                    for (String s : resultMapDatum.keySet()) {
                                        if(s.toLowerCase().equals(glOcrFiled)){
                                            List<TicketGeneralFieldEntity> valueMapList = (List<TicketGeneralFieldEntity>) resultMapDatum.get(s);
                                            if(!valueMapList.isEmpty()){
                                                if(valueMapList.get(0).getWord().equals(ocrFieldVield)){
                                                    HashMap<String, Object> mapData = new HashMap<>();
                                                    mapData.put("value", ocrFieldVield);
                                                    mapData.put("display", ocrFieldVield);
                                                    mapData.put("auth", "browse");

                                                    HashMap<String, Object> subMapData = new HashMap<>();
                                                    subMapData.put("fieldId", split[0]);
                                                    subMapData.put("tableName", tableName1);
                                                    subMapData.put("recordId", uuid1);
                                                    subMapData.put("fieldData", mapData);
                                                    subDataFieldList1.add(subMapData);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    subDataListMap1.put("uuid", uuid1);
                    subDataListMap1.put("hData", subDataFieldList1);
                    subDataListMap1.put("tableName", tableName1);
                    zhDataMaps.add(subDataListMap1);
                }
            }

            dataMap.put("master", masterDataList);
            dataMap.put("sub", zhDataMaps);

            HashMap<String, Object> map = new HashMap<>();
            map.put("code", "200");
            map.put("data", dataMap);
            return this.ok(JSONObject.toJSONString(map));
        }catch (Exception e){
            LOG.info("解析OCR识别结果异常：",e);
            resultMap.put("code","500");
            resultMap.put("message","解析OCR识别结果异常！！！！");
            return this.ok(JSONObject.toJSONString(resultMap));
        }
    }



    @Path("flushed")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces({ MediaType.APPLICATION_JSON })
    public String flushed(Map<String,Object> params){
        try {
            List<Map<String,Object>> sqlList = (List<Map<String, Object>>) params.get("sqlList");
            for (Map<String, Object> map : sqlList) {
                String sql =  StrKit.str(map.get("sql"));
                String fileUrl = StrKit.str(map.get("fileUrl"));
                List<Map<String, Object>> maps = DBKit.excuteSQL(sql, null);
                for (Map<String, Object> stringObjectMap : maps) {
                    String id = StrKit.str(stringObjectMap.get("id"));
                    Attachment attachment = attachmentManager.getAttachmentByFileURL(Long.valueOf(fileUrl));
                    attachment.setReference(Long.valueOf(id));
                    attachmentDAO.update(attachment);
                }


            }
        }catch (Exception exception){
            LOG.info("底表添加附件失败：",exception);
        }
        return JSON.toJSONString(params);
    }


    /**
     * 获取百度Ocr识别票据字段
     * @return
     */
    @Path("getBaiDuOcrField")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces({ MediaType.APPLICATION_JSON })
    public Response getBaiDuOcrField(){
        ArrayList<Map<String, Object>> baiDuOcrFields = oCRRecognizeService.getBaiDuOcrFields();
        return this.ok(JSONObject.toJSONString(baiDuOcrFields));
    }



}
